<?php

use app\logsystem\model\SystemFlowLog;
use app\websitext\logic\UsersHttpLogic;
use controller\BasicAdmin;
use libraries\DbCacheUtility;
use libraries\Tools;
use service\DataService;
use service\NodeService;
use think\Db;
use Zhuzhichao\BankCardInfo\BankCard;

/**  【业务函数】  **/
/**  【业务函数】  **/
/**  【业务函数】  **/

/**
 * 打印输出数据到文件
 * @param mixed $data 输出的数据
 * @param bool $force 强制替换
 * @param string|null $file
 */
function p($data, $force = false, $file = null)
{
    is_null($file) && $file = env('runtime_path') . date('Ymd') . '.txt';
    $str = (is_string($data) ? $data : (is_array($data) || is_object($data)) ? print_r($data, true) : var_export($data, true)) . PHP_EOL;
    $force ? file_put_contents($file, $str) : file_put_contents($file, $str, FILE_APPEND);
}

/**
 * RBAC节点权限验证
 * @param string $node
 * @return bool
 */
function auth($node)
{
    return NodeService::checkAuthNode($node);
}

/**
 * 设备或配置系统参数
 * @param string $name 参数名称
 * @param bool $value 默认是null为获取值，否则为更新
 * @return string|bool
 * @throws \think\Exception
 * @throws \think\exception\PDOException
 */
function sysconf($name, $value = null)
{
    static $config = [];
    if ($value !== null) {
        list($config, $data) = [[], ['name' => $name, 'value' => $value]];
        return DataService::save('SystemConfig', $data, 'name');
    }
    if (empty($config)) {
        $config = Db::name('SystemConfig')->column('name,value');
    }
    return isset($config[$name]) ? $config[$name] : '';
}

/**
 * 日期格式标准输出
 * @param string $datetime 输入日期
 * @param string $format 输出格式
 * @return false|string
 */
function format_datetime($datetime, $format = 'Y年m月d日 H:i:s')
{
    return date($format, strtotime($datetime));
}

/**
 * UTF8字符串加密
 * @param string $string
 * @return string
 */
function encode($string)
{
    list($chars, $length) = ['', strlen($string = iconv('utf-8', 'gbk', $string))];
    for ($i = 0; $i < $length; $i++) {
        $chars .= str_pad(base_convert(ord($string[$i]), 10, 36), 2, 0, 0);
    }
    return $chars;
}

/**
 * UTF8字符串解密
 * @param string $string
 * @return string
 */
function decode($string)
{
    $chars = '';
    foreach (str_split($string, 2) as $char) {
        $chars .= chr(intval(base_convert($char, 36, 10)));
    }
    return iconv('gbk', 'utf-8', $chars);
}

/**
 * 下载远程文件到本地
 * @param string $url 远程图片地址
 * @return string
 */
function local_image($url)
{
    return \service\FileService::download($url)['url'];
}

/**
 * description：获取某张表的字段
 * author：wanghua
 * @param $tablename
 * @return array
 */
function getTableFieldsByName($tablename, $is_prefix=''){
    if(!$tablename)return [];
    $prefix = $is_prefix?$is_prefix:config('database.prefix');
    if($prefix && false !== strpos($tablename, $prefix))
        $tablename = $prefix.$tablename;

    return Db::table($tablename)->getTableFields();
}
/**
 * description：换行输出（一般用于调试 eg：在循环中输出）
 * author：wanghua
 */
function brEcho($msg){
    echo '<br/>';
    echo $msg;
    echo '<br/>';
}

/**
 * description：常用表单类型
 * 1 input 2 select 3 radio 4 textarea 5 textarea_editer 6 img 7 checkbox 8 upload_file
 * author：wanghua
 * @param string $type
 * @param bool|false $all
 * @return array|string
 */
function getFormType($type='', $all=false){
    $arr = ['','input','date','time','select','radio','textarea','textarea_editer', 'img', 'checkbox', 'upload_file'];
    if($type){
        if(is_numeric($type)){
            return isset($arr[$type])?$arr[$type]:$type;
        }else{
            return $type;
        }
    }
    if($all){
        return $arr;
    }
    return '';
}

/**
 * description：根据下标获取字段类型（常用且可配置）
 * author：wh
 */
function getFieldsType($type='', $all=false){
    $arr = ['','int','tinyint','timestamp','float','decimal','varchar','char','text','longtext'];

    if($type){
        return empty($arr[$type])?$type:$arr[$type];
    }
    if($all){
        return $arr;
    }
    return $type;
}


/**
 * desc：读取base64编码后的图片并保存到path
 * author：wh
 * @param $base64_image_content
 * @return array|bool
 * @throws Exception
 */
function base64_image_content($base64_image_content){
    //preg_match匹配次数
    if(preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result) < 1){
        return false;
    }
    $mine = $result[1];
    //匹配出图片的格式
    $type = $result[2];
    $outer_req_url = '/static/upload/image/'.date('Y-m-d').'/'.date('H');
    $upload_dir = config('app.ROOT_PATH_PRO').'public'.$outer_req_url;
    if(!is_dir($upload_dir)){
        //检查是否有该文件夹，如果没有就创建，并给予最高权限
        mkdir($upload_dir, 0777, true);
    }

    $file_name = time().random_int(100000,999999).".{$type}";

    $file = $upload_dir .'/'. $file_name;
    //file_put_contents 返回字节数
    $size = file_put_contents($file, base64_decode(str_replace($result[1], '', $base64_image_content)));
    return [
        'real_path'=>$file,//物理路径
        'outer_req_url'=>request()->domain().$outer_req_url .'/'. $file_name,//外部访问路径
        'file_type'=>str_replace(';base64,','',str_replace('data:', '', $mine)),//mine
        'extension'=>$type,//扩展名
        'source_file_name'=>'',//源文件名称
        'new_filename'=>$file_name,//现文件名
        'size'=>$size,//大小
    ];
}


/**
 * description：查询当前数据库所有的表名
 * author：wh
 * @return mixed
 */
function getTables(){
    return array_column(Db::query('SHOW TABLES;'), 'Tables_in_'.config('database.database'));
}

/**
 * description：根据表名获取数据
 * author：wh
 * @param $fieldsname 要查询的字段名， 切记必须 有as ID 和 as title字段
 * @param $param web_goods:参数1-1,参数2-2,...
 * @return array
 */
function getDataByTbName($form_val, $fieldsname='',$condition=[]){
    if(!$form_val){
        return [];
    }
    $valarr = explode(',', $form_val);
    if(empty($valarr[0]))return [];
    $tablename = $valarr[0];
    if(in_array($tablename, getTables())){
        try{
            $obj = DB::table($tablename);
            $obj->field($fieldsname);
            //处理条件 area_id|>|0 ---字段|表达式|值
            if($condition){
                $arr = explode('|',htmlspecialchars_decode($condition));
                $obj->where($arr[0],$arr[1],$arr[2]);
            }
            //限制最大100个option
            $d = $obj->limit(100)->select();
            return $d;
        }catch (\Exception $e){
            throw new \think\Exception($e.';'.$tablename.';'.json_encode($condition));
        }
    }
    return [];
}
/**
 * description：获取项目根路径
 * author：wanghua
 */
if (!function_exists('get_root_path')) {
    function get_root_path(){
        return config('app.ROOT_PATH_PRO');
    }
}
/**
 * description：处理 form_value 字段为数组
 * author：wh
 */
function dealFormValueList($form_val, $fieldsname='*'){
    if(!$form_val){
        return [];
    }
    $valarr = explode(',', $form_val);
    if(empty($valarr[0]))return [];
    if(in_array($valarr[0], getTables())){
        //处理成 字段a as id 字段b as title
        $str_field = explode('-', $fieldsname);
        if(empty($str_field[0]) || empty($str_field[1])){throw new Exception('表单可选值 字段格式错误');}
        $fieldsname = $str_field[0].' as id,'.$str_field[1].' as title';
        return getDataByTbName($form_val, $fieldsname,empty($valarr[1])?[]:$valarr[1]);
    }else{
        $r = [];
        foreach($valarr as $k => $v){
            $temp = [];
            $t = explode(':', $v);

            $temp['id'] = $t[0];
            $temp['title'] = $t[1];
            array_push($r, $temp);
        }
        return $r;
    }
}


/**
 * description：删除目录下的文件：权限不足可能导致失败
 * author：wanghua
 * @param $path
 * @return bool
 */
//function deleteFile($path=''){
//    if(!$path || !file_exists($path))return false;
//    $files = scandir($path);
//    if($files){
//        foreach ($files as $key => $val){
//            if(!in_array($val, ['.', '..'])){
//                unlink($path.$val);
//            }
//        }
//        return true;
//    }else{
//        return false;
//    }
//}

if(!function_exists('log_to_write_txt')){
    /**
     * 记录日志到文本-日志文件可即时删除
     * wanghua
     * @param string $data
     * @param string $filepath
     */
    function log_to_write_txt($data = 'test', $filepath = '/runtime/wac_log.txt'){
        $filepath = config('app.ROOT_PATH_PRO').$filepath;
        $str = '';
        file_put_contents($filepath, is_object($data)||is_array($data)?$str.json_encode($data)."\n":$str.$data."\n", FILE_APPEND);
    }
}


/**
 * desc：全局加密规则[统一用它加密]
 * 数据加密,但规则会变化
 * author：wh
 */
function encrypt_str($str){
    return base64_encode($str);
}

/**
 * desc：全局解密
 * author：wh
 * @param $str
 * @return false|string
 */
function de_encrypt_str($str){

    return base64_decode($str);
}

/**
 * desc：全局统一密码加密
 * author：wh
 * @param $str
 */
function encrypt_password($str){

    return md5($str . config('app.ae_agent_common_key'));
}

//逗号分隔符，四舍五入保留两位小数
function amount_format($money){
    return number_format($money,2);
}

//四舍五入保留两位小数
function amount_round($money){
    if(strpos($money, '.') !== false){
        return round($money,2);
    }
    return $money.'.00';
}

/**
 * desc：
 * author：wh
 */
function template_replace($string, $from_param = [], $to_param = []){

    $source_param = $from_param ? $from_param : config('email.template_fields');

    $tmp_str = $string;
    if(!empty($to_param)){
        foreach ($source_param as $field){
            foreach ($to_param as $key =>$val){
                if(':'.$field == ':'.$key){
                    $tmp_str = str_replace(':'.$field, $val, $tmp_str);
                }
            }
        }
    }
    return $tmp_str;
}

/**
 * desc：
 * //解析,先用|分割，再用,分割。第1个为事件类型，第二个为函数名称，后面就是参数取值
 *  //eg：onclick,toChangeRemitChannel|id=ele_id_settlement_type,class=ele_class_settlement_type
 * author：wh
 * @param $str
 */
function parse_trigger_functions($radio_trigger_functions){
    if(empty($radio_trigger_functions)){
        return '';
    }
    $exp_arr = explode('|', $radio_trigger_functions);
    $var_event = explode(',', $exp_arr[0])[0];
    $var_function = explode(',', $exp_arr[0])[1];
    return [
        'var_event'=>$var_event,//事件名
        'var_function'=>$var_function,//函数名
        //'var_function_complete'=>$var_event."'".$var_function."()'",//完整的函数
    ];
}

/**
 * desc：将驼峰式命名 转换为 下划线命名
 * author：wh
 * @param $str
 * @return string
 */
function convertLineUnder($str){

    return Tools::convertLineUnder($str);
}

/**
 * desc：转换用户信息[单条数据]
 * author：wh
 */
//function changeUserInfo($userids, $key=''){
//    $users_obj = (new UsersHttpLogic());
//    $req_data = $users_obj->getUsersByIds($userids);
//    return $key?$req_data[0][$key]:'';
//}

/**
 * desc：根据id获取表数据
 * author：wh
 * @param $table
 * @param $id
 * @return mixed
 */
function getTableDataById($table, $id){
    $obj = Db::name($table);
    $obj->where(['is_deleted'=>0]);
    $obj->where(['id'=>$id]);
    return DbCacheUtility::getOne($obj);
}

/**
 * desc：检查表是否可以同步数据到Redis
 * author：wh
 * @param $table
 * @return bool true:可以同步；false:禁止同步
 * @throws \think\Exception
 * @throws \think\exception\PDOException
 */
function tableIsRedisSync($table){
    $table = BasicAdmin::DefFix.$table;
    //忽略表
    $ignore_tables = sysconf('ignore_tables');
    //忽略特征
    $table_feature = sysconf('table_feature');
    //过滤特征表
    foreach (explode(',', $table_feature) as $feature){
        if(false !== strpos($table, $feature)) return  false;
    }

    //过滤忽略表
    if(in_array($table, explode(',', $ignore_tables))) return false;
    return true;
}

/**
 * [同步sql到.sql文件]
 *
 * @param $sql
 * @param string $title
 * @example
 * @see
 * @link
 */
function auto_sync_sql($sql, $title = '', $config=[]){
    if(empty($config)) return false;//直接结束
    if(!config('app.app_debug')) return false;//非调试模式直接结束

    $__file__ = empty($config['file'])?:$config['file'];
    $__line__ = empty($config['line'])?:$config['line'];

    //目录前缀
    $dir =  config('app.ROOT_PATH_PRO').'/sql/';
    if(!file_exists($dir)){
        mkdir($dir, 0777, true);
    }
    //sql文件存储名称
    if(empty($config['sql_file'])){
        $sql_file = 'sql-sync-auto';
    }else{
        $sql_file = $config['sql_file'];
    }
    $dir .= $sql_file.sysconf('app_version');//添加版本号
    $dir .= '.sql';//后缀
    $title = "\r\n".'-- '.date('Ymd H:i:s').' '.$title.' '.$__file__.' '.$__line__."\r\n";//说明

    file_put_contents($dir, $title.$sql."\r\n", FILE_APPEND);
}


/**
 * desc：格式化json
 * author：wh
 * @param $data
 * @return false|string
 */
function encodeJson($data){
    //JSON_PARTIAL_OUTPUT_ON_ERROR 512 支持表情
    //JSON_UNESCAPED_UNICODE 256 //不支持表情
    return json_encode($data, JSON_PARTIAL_OUTPUT_ON_ERROR);
}

/**
 * desc：格式化json
 * author：wh
 * @param $data
 * @return false|string
 */
function encodeJsonUnicode($data){
    //JSON_PARTIAL_OUTPUT_ON_ERROR 512 支持表情
    //JSON_UNESCAPED_UNICODE 256 //不支持表情
    return json_encode($data, JSON_UNESCAPED_UNICODE);
}

/**
 * desc：将数字字符串转换为金钱格式
 * 保留两位
 * author：wh
 * @param $num
 * @return float|int|string eg：231225.00
 */
function revert_number_money($num){
    if(!is_numeric($num)) return '0.00';
    return sprintf('%.2f', $num);
}

/**
 * desc：设置系统流程日志(写入日志到数据库)
 * log_to_write_txt 函数可写数据到日志文件
 * author：wh
 * @param string $title
 * @param string $content
 * @return int|string
 */
function system_flow_log($title='', $content=''){
    $content = is_string($content)?$content:encodeJsonUnicode($content);
    return (new SystemFlowLog())->addLog($title, $content);
}

/**
 * []
 *
 * @return mixed
 * @link
 * @example
 * @see
 */
function get_input(){
    $input = file_get_contents("php://input");
    return json_decode($input, true);
}